#pragma once

#include "synchronizacja.h"
#include "baza.h"


//2 ponizsze klasy sa wystarczajaco jasne, nie ma co komentowac-bazyl
struct Wyjatek
   {
   string opis;
   Wyjatek(const string & opis) : opis(opis) {}
   };

class WyjatekSkanera : public Wyjatek
   {
   public:
      WyjatekSkanera() : Wyjatek("Przerwane skanowanie") {}
   };

//abstakcyjna klasa skanera, bedaca podstawa do pozniejszych implementacji skanerow - bazyl
class ISkaner
   {
   public:
      struct Plik
         {
         string nazwa;
         unsigned long long rozmiar;
         bool katalog;
         };

      typedef vector<Plik> Pliki;

      virtual ~ISkaner() {};
      virtual Pliki PobierzPliki(ostream & plik_log) = 0;
      virtual bool WyjdzZKatalogu(ostream & plik_log) = 0;
      virtual bool WejdzDoKatalogu(const string & katalog, ostream & plik_log) = 0;
      virtual bool PolaczPonownie() = 0;
   };

ISkaner * OtworzFTP(const string & komputer, ostream &);
ISkaner * OtworzNetBios(const string & komputer, ostream &);

enum Usluga
   {
   UslugaFTP = 0,
   UslugaNetBios = 1,
   UslugaKoniec = 2
   };

struct DaneUslugi
   {
   Usluga usluga;
   string nazwa;
   ISkaner * (* Kreator)(const string & komputer, ostream &);
   };

extern DaneUslugi dane_uslug[];

class WatekSkanujacy
   {
   protected:
      typedef vector<string> Katalogi;
      SekcjaKrytyczna sekcja;
      bool czy_przerwac;

      string nazwa_komputera;
      string ip;
      Usluga usluga;
      ISkaner * skaner;
      IBaza * baza;
      Katalogi katalogi;
      unsigned long int id_watku;


	static void * Watek(void *);
      bool PolaczPonownie(ostream & plik_log);
      void RozpocznijSkanowanie(void);
      void SkanujKatalog(unsigned katalog, unsigned poziom_katalogu, ostream & plik_log);

   public:
      WatekSkanujacy(const string & nazwa_komputera, const string & ip, Usluga usluga);
      unsigned long int UruchomWatek();
      void Przerwij();
      string DajNazwe(){
        return nazwa_komputera;
    }
   };

class ZarzadcaSkanowania
   {
   public:
      enum StanSkanera
         {
         AktywneSkanowanie,
         PrzerywaneSkanowanie,
         Zatrzymany,
         Nieaktywny
         };

   protected:
      struct DaneWatku
         {
			 unsigned long int uchwyt;
			 Usluga usluga;
			 bool zakonczono;
			 time_t start;
			 bool polaczony;
         };
	   typedef map<WatekSkanujacy *, DaneWatku> WatkiSkanujace;
	   typedef vector<string> Komputery;
	   typedef vector<string> IPs;
	   static ZarzadcaSkanowania * zarzadca_skanowania;
	   static SekcjaKrytyczna sekcja_zarzadcy;
	   static void *WatekZarzadcy(void * parametr);

      SekcjaKrytyczna sekcja_zmiennych;
      StanSkanera aktualny_stan;
      int maksymalna_ilosc_watkow;
      WatkiSkanujace watki_skanujace;
	   pthread_t	 watek_zarzadcy;

	IPs ips;
      Komputery komputery;
      unsigned numer_skanowanego;
      unsigned numer_uslugi;
      ZarzadcaSkanowania();
      void FunkcjaZarzadzajaca();
      void WczytajListeHostow(const string & nazwa_pliku);

   public:
      ~ZarzadcaSkanowania();
	pthread_attr_t	thread_attr;
      void WatekSkanujacyZakonczony(WatekSkanujacy*);
      void WatekSkanujacyPolaczony(WatekSkanujacy*);
      void Przerwij();
      StanSkanera JakiStan();

      static ZarzadcaSkanowania & PobierzZarzadceSkanowania();

   };
